/**
 * Created by tdzl2003 on 6/19/16.
 */

import { EventEmitter } from 'fbemitter';

export default class FormContext extends EventEmitter {
  constructor({ defaultValues, onSubmit }) {
    super();
    this.values = defaultValues || {};
    this.onSubmit = onSubmit;
  }
  fields = {

  };
  validationStatus = {

  };
  isSubmitting = false;
  getValue(key) {
    return this.values[key];
  }
  setValue(key, value) {
    this.values[key] = value;
    if (this.fields[key]) {
      try {
        this.fields[key].validate(this.values[key]);
        delete this.validationStatus[key];
      } catch (e) {
        this.validationStatus[key] = e;
      }
    }
    this.emit('onValueChange', this.values);
  }
  isFieldValid(name) {
    return !this.validationStatus[name];
  }
  get isValid() {
    return Object.keys(this.validationStatus).length === 0;
  }
  addField(name, options) {
    const { defaultValue } = options || {};
    if (this.fields[name]) {
      throw new Error(`Duplicated field with name ${name}`);
    }
    this.fields[name] = options;
    if (this.values[name] === undefined) {
      this.values[name] = defaultValue;
    }
    try {
      options.validate(this.values[name]);
    } catch (e) {
      this.validationStatus[name] = e;
    }
    this.emit('onFieldChange', this.values);
  }
  removeField(name) {
    delete this.fields[name];
    delete this.values[name];
  }
  async submit() {
    if (this.isSubmitting) {
      throw new Error('Another submit processs running.');
    }
    this.isSubmitting = true;
    this.emit('onSubmitBegin', this.values);
    try {
      const result = await this.onSubmit(this.values);
      this.emit('onSubmitResult', result);
    } catch (e) {
      if (__DEV__) {
        console.warn(e);
      }
      this.emit('onSubmitFail', e);
    } finally {
      this.isSubmitting = false;
      this.emit('onSubmitEnd');
    }
  }
}
